package com.ysten.cntv.tsop.content.validation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.ysten.cntv.cms.entity.CatgItem;
import com.ysten.cntv.cms.service.category.CatgItemService;
import com.ysten.cntv.cms.service.programseries.ProgramService;
import com.ysten.cntv.cms.service.programseries.ProgramseriesService;
import com.ysten.cntv.tsop.commons.entity.RcmdTypeDic;
import com.ysten.cntv.tsop.commons.service.ValidateContentService;
import com.ysten.cntv.tsop.content.entity.Channel;
import com.ysten.cntv.tsop.content.entity.ChannelSeriesRel;
import com.ysten.cntv.tsop.content.entity.Panel;
import com.ysten.cntv.tsop.content.entity.PanelItem;
import com.ysten.cntv.tsop.content.entity.PanelItemRel;
import com.ysten.cntv.tsop.content.entity.Topic;
import com.ysten.cntv.tsop.content.entity.TopicSeriesRel;
import com.ysten.core.modules.constant.CoreConstants;
import com.ysten.core.modules.constant.SysDicConstants;
import com.ysten.core.modules.exceptions.ValidationException;

@Component
public class ContentValidation
{
    private static Logger logger = LoggerFactory.getLogger(ContentValidation.class);

    @Autowired
    private ValidateContentService vcService;

    @Autowired
    private ProgramseriesService programseriesService;

    @Autowired
    private ProgramService programService;

    @Autowired
    private CatgItemService catgItemService;

    /**
     * <校验频道数据>
     *
     * @param channelId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateChannel(Long channelId)
    {
        return validateT(channelId, new DataInteface<Channel>()
        {
            @Override
            public Channel getContent(Long channelId)
            {
                return vcService.getChannel(channelId);
            }

            @Override
            public boolean statusOk(Channel content)
            {
                return SysDicConstants.ONLINESTATUS_ONLINE == content.getOnlineStatus().intValue();
            }

            @Override
            public String getDataType()
            {
                return "Channel";
            }
        });
    }

    /**
     * <校验频道的节目集数据>
     *
     * @param channelId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateChannelSeriesRels(Long channelId)
    {
        logger.debug("Enter func[validateChannelSeriesRels], channelId : ", new Object[] {channelId});

        List<HashMap<String, Object>> checkList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> checkMap = null;
        Long programSerieId = null;
        String numbers = null;

        List<ChannelSeriesRel> relList = vcService.getChannelSeriesRels(channelId);
        for (ChannelSeriesRel csr : relList)
        {
            checkMap = new HashMap<String, Object>();
            programSerieId = csr.getProgramSeriesId();
            checkMap.put(CoreConstants.KEY_PROGRAMSERIESID, programSerieId);

            numbers = csr.getProgramSeriesNumbers();
            if (!StringUtils.isEmpty(numbers))
            {
                checkMap.put(CoreConstants.KEY_PROGRAMSERIESNUM, toArrayList(numbers));
            }
            checkList.add(checkMap);
        }

        String ret = programseriesService.doCheckProgramSeries(checkList);
        logger.debug("Exit func[validateChannelSeriesRels], validate result : ", new Object[] {ret});
        return ret;
    }

    /**
     * <校验专题数据>
     *
     * @param channelId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateTopic(Long topicId)
    {
        return validateT(topicId, new DataInteface<Topic>()
        {
            @Override
            public Topic getContent(Long topicId)
            {
                return vcService.getTopic(topicId);
            }

            @Override
            public boolean statusOk(Topic content)
            {
                return SysDicConstants.ONLINESTATUS_ONLINE == content.getOnlineStatus().intValue();
            }

            @Override
            public String getDataType()
            {
                return "Topic";
            }
        });
    }

    /**
     * <校验专题的节目集数据>
     *
     * @param topicId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateTopicSeriesRels(Long topicId)
    {
        logger.debug("Enter func[validateTopicSeriesRels], topicId : ", new Object[] {topicId});

        List<HashMap<String, Object>> checkList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> checkMap = null;
        Long programSerieId = null;
        String numbers = null;

        List<TopicSeriesRel> relList = vcService.getTopicSeriesRels(topicId);
        for (TopicSeriesRel tsr : relList)
        {
            checkMap = new HashMap<String, Object>();
            programSerieId = tsr.getProgramSeriesId();
            checkMap.put(CoreConstants.KEY_PROGRAMSERIESID, programSerieId);

            numbers = tsr.getProgramSeriesNumbers();
            if (!StringUtils.isEmpty(numbers))
            {
                checkMap.put(CoreConstants.KEY_PROGRAMSERIESNUM, toArrayList(numbers));
            }
            checkList.add(checkMap);
        }

        String ret = programseriesService.doCheckProgramSeries(checkList);
        logger.debug("Exit func[validateTopicSeriesRels], validate result : ", new Object[] {ret});
        return ret;
    }

    /**
     * <校验节目集数据>
     *
     * @param topicId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateProgramSeries(Long programSeriesId)
    {
        logger.debug("Enter func[validateProgramSeries], programSeriesId : ", new Object[] {programSeriesId});

        List<HashMap<String, Object>> checkList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> checkMap = null;

        checkMap = new HashMap<String, Object>();
        checkMap.put(CoreConstants.KEY_PROGRAMSERIESID, programSeriesId);
        checkList.add(checkMap);

        String ret = programseriesService.doCheckProgramSeries(checkList);
        logger.debug("Exit func[validateProgramSeries], validate result : ", new Object[] {ret});
        return ret;
    }

    /**
     * <校验节目集以及包含的节目>
     *
     * @param topicId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateProgramSeriesRels(Long programSeriesId)
    {
        logger.debug("Enter func[validateProgramSeriesRels], programSeriesId : ", new Object[] {programSeriesId});

        List<HashMap<String, Object>> checkList = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> checkMap = null;

        checkMap = new HashMap<String, Object>();
        checkMap.put(CoreConstants.KEY_PROGRAMSERIESID, programSeriesId);

        List<Long> numbers = programseriesService.getProgramIdByProgramSeriesId(programSeriesId);
        if (!CollectionUtils.isEmpty(numbers))
        {
            checkMap.put(CoreConstants.KEY_PROGRAMSERIESNUM, numbers);
        }
        checkList.add(checkMap);

        String ret = programseriesService.doCheckProgramSeries(checkList);
        logger.debug("Exit func[validateProgramSeriesRels], validate result : ", new Object[] {ret});
        return ret;
    }

    /**
     * <校验节目数据>
     *
     * @param programId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validateProgram(Long programId)
    {
        List<Long> idList = new ArrayList<Long>();
        idList.add(programId);

        return programService.doCheckProgram(idList);
    }

    public String validateCategory(Long catgId)
    {
        return validateT(catgId, new DataInteface<CatgItem>()
        {
            @Override
            public CatgItem getContent(Long catgId)
            {
                return catgItemService.getCatgItemInfoById(catgId);
            }

            @Override
            public boolean statusOk(CatgItem content)
            {
                return CoreConstants.STATUS_ONLINE.equalsIgnoreCase(content.getStatus());
            }

            @Override
            public String getDataType()
            {
                return "Catg";
            }
        });

    }

    /**
     * <校验panel数据>
     *
     * @param panelId
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String validatePanel(Long panelId)
    {
        return validateT(panelId, new DataInteface<Panel>()
        {
            @Override
            public Panel getContent(Long panelId)
            {
                return vcService.getPanel(panelId);
            }

            @Override
            public boolean statusOk(Panel content)
            {
                return SysDicConstants.ONLINESTATUS_ONLINE == content.getOnlineStatus().intValue();
            }

            @Override
            public String getDataType()
            {
                return "Panel";
            }
        });

    }

    public String validatePanelRels(Long panelId)
        throws ValidationException
    {
        logger.debug("Enter func[PanelRels], panelId : ", new Object[] {panelId});

        StringBuilder ret = new StringBuilder();

        List<PanelItemRel> relList = vcService.getPanelSeriesRels(panelId);
        PanelItem pi = null;
        Long parentId = null;
        String checkRet = null;

        for (PanelItemRel pir : relList)
        {
            pi = vcService.getPanelItem(pir.getPanelItemId());
            parentId = pi.getParentId();
            // 非接口数据
            if (null == parentId)
            {
                checkRet = validatePanelItem(pi);
            }
            else if (-1 == parentId)
            {
                // 接口数据
                List<PanelItem> childItems = vcService.getPanelItemList(pi.getId());
                checkRet = validatePanelItemList(childItems);
            }
            ret.append(checkRet);
        }

        logger.debug("Exit func[PanelRels], result : ", new Object[] {ret});
        return ret.toString();
    }

    private String validatePanelItemList(List<PanelItem> childItems)
        throws ValidationException
    {
        StringBuilder sb = new StringBuilder();
        String ret = null;
        for (PanelItem pi : childItems)
        {
            ret = validatePanelItem(pi);
            if (!StringUtils.isEmpty(ret))
            {
                // 暂时使用下面的返回信息
                // sb.append("contentId :").append(pi.getContentId()).append(ret).append(";");
                sb.append(ret).append("; ");
            }
        }
        return sb.toString();
    }

    private String validatePanelItem(PanelItem pi)
        throws ValidationException
    {
        logger.debug("Enter func[validatePanelItem], panelItem : ", new Object[] {pi});

        Long type = pi.getType();
        Long contenId = pi.getContentId();

        RcmdTypeDic typeDic = vcService.findRcmdTypeDicById(type);
        Integer contentTypeId = typeDic.getContenttypeId();

        if (null == contentTypeId)
        {
            throw new ValidationException("panelItem's rcmdType is error.");
        }

        String ret = null;

        switch (contentTypeId)
        {
            case CoreConstants.CONTENTTYPE_PROGRAMSERIES:
            {
                ret = validateProgramSeries(contenId);
                break;
            }
            /*
             * case CoreConstants.CONTENTTYPE_PROGRAM: { ret = validateProgram(contenId); break; }
             */
            case CoreConstants.CONTENTTYPE_CATG:
            case CoreConstants.CONTENTTYPE_CATG_V1:
            case CoreConstants.CONTENTTYPE_CATG_V2:
            {
                ret = validateCategory(contenId);
                break;
            }
            default:
            {
                logger.debug("Inner func[validatePanelItem], no need to validate type : ", new Object[] {contentTypeId});
            }
        }

        logger.debug("Exit func[validatePanelItem], result : ", new Object[] {ret});
        return ret;
    }

    private List<Long> toArrayList(String numbers)
    {
        List<Long> retList = new ArrayList<Long>();
        String[] numberArr = numbers.split(",");
        for (String number : numberArr)
        {
            retList.add(Long.valueOf(number));
        }
        return retList;
    }

    private interface DataInteface<T>
    {
        T getContent(Long contentId);

        boolean statusOk(T content);

        String getDataType();
    }

    private <T> String validateT(Long contentId, DataInteface<T> dataInf)
    {
        logger.debug("Enter func[validateT], contentId : ", new Object[] {contentId});

        T content = dataInf.getContent(contentId);
        StringBuilder ret = new StringBuilder();
        if (null == content)
        {
            ret.append(dataInf.getDataType()).append(" [").append(contentId).append("] ").append("not exist");
            logger.debug("Exit func[validateT], result : ", new Object[] {ret});
            return ret.toString();
        }

        if (!dataInf.statusOk(content))
        {
            ret.append(dataInf.getDataType()).append(" [").append(contentId).append("] ").append("not online");
            logger.debug("Exit func[validateT], result : ", new Object[] {ret});
            return ret.toString();
        }

        logger.debug("Exit func[validateT], result : ", new Object[] {ret});
        return ret.toString();
    }
}
